package com.booter.webflux.http.factory;

import com.booter.webflux.http.annotation.ServiceApi;
import com.booter.webflux.http.processor.CreateProcessor;
import org.apache.commons.lang3.StringUtils;
import org.reflections.Reflections;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.reflections.util.ConfigurationBuilder;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.Set;

public class HttpBeanDefinitionRegistry implements ApplicationContextAware {

    private String packageName;
    private CreateProcessor processor;

    public HttpBeanDefinitionRegistry(String packageName, CreateProcessor processor) {
        this.packageName = packageName;
        this.processor = processor;
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ConfigurableApplicationContext context = (ConfigurableApplicationContext) applicationContext;
        DefaultListableBeanFactory dbf = (DefaultListableBeanFactory) context.getBeanFactory();
        Reflections reflections = new Reflections(new ConfigurationBuilder().forPackages(packageName).addScanners(new TypeAnnotationsScanner()));
        Set<Class<?>> set = reflections.getTypesAnnotatedWith(ServiceApi.class);
        set.forEach(s -> {
            RootBeanDefinition definition = new RootBeanDefinition();
            definition.setBeanClass(HttpFactoryBean.class);
            definition.setLazyInit(true);
            definition.getConstructorArgumentValues().addGenericArgumentValue(s);
            definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
            definition.setAttribute("processor", processor);
            String name = StringUtils.uncapitalize(s.getSimpleName());
            dbf.registerBeanDefinition(name, definition);
        });
    }
}
